/* Decomposition.ado (STATA)
	Decomposition of asset prices.
	by Ralph Koijen & Motohiro Yogo */

#delimit ;

program Decomposition;
args n y;

di `y';


/* Load data */

u "../3 Estimation/Consumption`n'" if inrange(year,`y'-1,`y'), clear;

/* Construct holdings of countries not in sample at t-1 */

egen int year_country = min(year), missing by(country);

egen TQamount = total(Qamount*(year_country==`y')), missing by(year counter_euro type);

/* Construct lag variables */

qui foreach var of varlist Lfx Lmb yield {;
	egen `var'_ = total(`var'/(year==`y'-1 & Iycounter_euro)), missing by(counter_euro type);
};

/* Construct future variables */

qui foreach var of varlist Lfx Lmb {;
	egen _`var' = total(`var'/(year==`y' & Iycounter_euro)), missing by(counter_euro type);
};


/* STEP 0: Check code
   STEP 1: Portfolio flows and asset quantities
   STEP 2: Macro variables
   STEP 3-8: Latent demand and outside assets by country group */

qui forval i = 0/8 {;

	/* Asset quantities */

	egen QmarketCF = total((Qmarket-TQamount*(`i'<=6))/(year==`y'-(`i'==0) & Iycounter_euro)), missing by(counter_euro type);

	/* Macro variables */

	foreach var of varlist Lrelpi $macro {;
		egen `var'CF = total(`var'/(year==`y'-(`i'<=1) & Iycounterpart)), missing by(counterpart type);
	};

	/* Define country groups */

	gen byte Igroup = (year==`y'-1 & country_group>`i'-3) | (year==`y' & country_group<=`i'-3);

	/* Outside assets */

	egen outsideCF = total(outside/(Igroup & Iycountry)), missing by(country type);

	/* Demand shifters */

	gen shifter = b_cons+eps if Igroup;

	foreach var of varlist $macro {;
		replace shifter = shifter+b_`var'*`var'CF if Igroup;
	};

	foreach var of varlist $bilateral $dummies {;
		replace shifter = shifter+b_`var'*`var' if Igroup;
	};

	/* Aggregate demand shifters */

	gen shifterA = bA_cons+epsA if Igroup;

	/* Initial guess for prices */

	if `i'==0 {;
		gen LfxCF = Lfx_;
		gen LmbCF = Lmb_ if type!=1;

		gen shiftCF = 0;
	};
	else {;
		gen LfxCF = Lfx`=`i'-1';
		gen LmbCF = Lmb`=`i'-1' if type!=1;

		gen shiftCF = shift`=`i'-1';
	};

	if `i'==7 {;
		replace LfxCF = _Lfx if missing(LfxCF);
		replace LmbCF = _Lmb if type!=1 & missing(LmbCF);
	};

	/* Update ST debt prices */

	replace LmbCF = bC_cons+epsC if type==1 & Igroup;

	foreach var of varlist $macro {;
		replace LmbCF = LmbCF+bC_`var'*`var'CF if type==1 & Igroup;
	};

	sort counter_euro type LmbCF;
	by counter_euro type: replace LmbCF = LmbCF[1] if type==1;

	/* Solve for prices */

	forval s = 1/$Nstep {;

		/* Expected returns in USD */

		gen EretCF = c_Lmb*LmbCF+c_Lrealfx*(LfxCF-LrelpiCF)+c_cons;

		/* Adjust expected returns to local currency */

		egen Eret_LCU = total(EretCF*(type==1 & Iycounterpart)), missing by(year country);

		replace EretCF = EretCF-Eret_LCU;

		drop Eret_LCU;

		/* Construct inner portfolio weights */

		gen delta = exp(b_Eret*EretCF+shifter-shiftCF);

		egen Sdelta = total(delta), missing by(year country type);
		replace Sdelta = 1+Sdelta;

		gen weight = delta/Sdelta;

		drop EretCF delta;

		/* Check outside portfolio weights */

		gen DweightO = 1/Sdelta-outsideA/wealthA if Iycountry;

		/* Construct outer portfolio weights */

		gen Sdelta1 = Sdelta^bA_LSrw1*exp(shifterA) if type==1;
		replace Sdelta1 = Sdelta^bA_LSrw2*exp(shifterA) if type==2;
		replace Sdelta1 = Sdelta^bA_LSrw3*exp(shifterA) if type==3;

		egen Sdelta2 = total(Sdelta1*Iycountry), missing by(year country);

		gen weightA = Sdelta1/Sdelta2;

		drop Sdelta*;

		/* Construct wealth before portfolio choice */

		egen wealth1CF = total(amount*exp(LmbCF-Lmb+LfxCF-Lfx)) if year==`y'-(`i'==0), missing by(year country);
		replace wealth1CF = wealth1CF+outsideCF if year==`y'-(`i'==0);

		sort country wealth1CF;
		by country: replace wealth1CF = wealth1CF[1];

		/* Construct wealth after portfolio choice */

		egen Tweight = total(weight*weightA), missing by(year country);

		gen wealth2CF = outsideCF/(1-Tweight);

		drop Tweight;

		/* Check convergence of wealth */

		gen gap_W = ln(wealth2CF)-ln(wealth1CF) if type==1 & Iycountry;

		sum gap_W;
		local gap_W = max(abs(r(min)),abs(r(max)));

		drop wealth1CF;

		/* Update demand shifters */

		replace shiftCF = shiftCF+$step_W*gap_W if !missing(gap_W);

		sort country gap_W;
		by country: replace shiftCF = shiftCF[1];

		drop gap_W;

		/* Construct demand */

		egen demand = total(wealth2CF*weight*weightA) if Igroup, missing by(counter_euro type);

		drop weight* wealth2CF;

		/* Check convergence of demand */

		gen gap = ln(demand)-(LmbCF+LfxCF+ln(QmarketCF)) if Iycounter_euro;

		sum gap if counter_euro!="USA" | type!=1;
		local gap = max(abs(r(min)),abs(r(max)));

		sum gap if counter_euro=="USA" & type==1;
		local gap_US = max(abs(r(min)),abs(r(max)));

		drop demand;

		/* Update exchange rates */

		replace LfxCF = LfxCF+$step_fx*gap/(1-b_Eret*c_Lrealfx) if counter_euro!="USA" & type==1;

		sort counter_euro type gap;
		by counter_euro type: replace LfxCF = LfxCF[1];

		gsort counterpart type year -Iycounterpart;
		by counterpart: replace LfxCF = LfxCF[1];

		/* Update asset prices */

		replace LmbCF = LmbCF+$step_mb*gap/(1-b_Eret*c_Lmb) if type!=1;

		sort counter_euro type gap;
		by counter_euro type: replace LmbCF = LmbCF[1];

		drop gap;

		/* Exit if converged */

		if (`gap_W'<$Mgap & `gap'<$Mgap) | `s'==$Nstep {;

			/* Summary */

			nois di `i' _skip(5) `s' _skip(5) `gap_W' _skip(5) `gap' _skip(5) `gap_US';

			nois table type, nototals nformat(%8.2f)
				stat(count DweightO) stat(median DweightO) stat(iqr DweightO) stat(min DweightO) stat(max DweightO);

			drop DweightO;

			/* Save estimates */

			gen Lfx`i' = LfxCF;
			gen Lmb`i' = LmbCF;
			gen yield`i' = -LmbCF/maturity;

			gen shift`i' = shiftCF;

			continue, break;
		};

		drop DweightO;
	};

	drop *CF Igroup shifter*;
};

/* Fix variables */

qui replace Name = "Euro" if counter_euro=="EUR";

/* Keep estimates only */

qui keep if year==`y' & Iycounter_euro;

keep year counter_euro Name type market Lfx* Lmb* yield*;

/* Construct changes */

qui foreach var of varlist Lfx Lmb yield {;
	gen D`var' = `var'-`var'_;
	gen D`var'1 = `var'1-`var'_;

	forval i = 2/7 {;
		gen D`var'`i' = `var'`i'-`var'`=`i'-1';
	};

	gen D`var'8 = `var'-`var'7;
	gen D`var'9 = `var'-`var'2;
};

/* Label variables */

order Lfx* Lmb* yield* DLfx* DLmb* Dyield*, after(market);
order Lfx_, before(Lfx0);
order Lmb_, before(Lmb0);
order yield_, before(yield0);

label var Lfx_		"Exchange rate: Previous year";
label var Lfx0		"Exchange rate: Check code";
label var Lfx1		"Exchange rate: Flows and quantities";
label var Lfx2		"Exchange rate: Macro";

label var Lmb_		"Price: Previous year";
label var Lmb0		"Price: Check code";
label var Lmb1		"Price: Flows and quantities";
label var Lmb2		"Price: Macro";

label var yield_	"Yield: Previous year";
label var yield0	"Yield: Check code";
label var yield1	"Yield: Flows and quantities";
label var yield2	"Yield: Macro";

label var DLfx		"Exchange rate change";
label var DLfx1		"Exchange rate change: Flows and quantities";
label var DLfx2		"Exchange rate change: Macro";
label var DLfx9		"Exchange rate change: Total demand";

label var DLmb		"Price change";
label var DLmb1		"Price change: Flows and quantities";
label var DLmb2		"Price change: Macro";
label var DLmb9		"Price change: Total demand";

label var Dyield	"Yield change";
label var Dyield1	"Yield change: Flows and quantities";
label var Dyield2	"Yield change: Macro";
label var Dyield9	"Yield change: Total demand";

forval i = 3/8 {;
	label var Lfx`i'	"Exchange rate: country_group==`=`i'-3'";
	label var Lmb`i'	"Price: country_group==`=`i'-3'";
	label var yield`i'	"Yield: country_group==`=`i'-3'";

	label var DLfx`i'	"Exchange rate change: country_group==`=`i'-3'";
	label var DLmb`i'	"Price change: country_group==`=`i'-3'";
	label var Dyield`i'	"Yield change: country_group==`=`i'-3'";
};

/* Save estimates */

if `y'>2004+(`n'==1)*8 {;
	qui append using Decomposition`n';
};

sort year counter_euro type;

qui save Decomposition`n', replace;

end;
